/*
 * Wazuh cmdLineParser
 * Copyright (C) 2015, Wazuh Inc.
 * October 26, 2023.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef _CMD_ARGS_PARSER_HPP_
#define _CMD_ARGS_PARSER_HPP_

#include "json.hpp"
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

/**
 * @brief Class to parse command line arguments.
 */
class CmdLineArgs
{
public:
    /**
     * @brief Constructor for CmdLineArgs.
     * @param argc Number of arguments.
     * @param argv Arguments.
     */
    explicit CmdLineArgs(const int argc, const char* argv[])
        : m_configurationFilePath {paramValueOf(argc, argv, "-c")}
        , m_waitTime {paramValueOf(argc, argv, "-s", std::make_pair(false, "0"))}
        , m_inputFiles {splitActions(paramValueOf(argc, argv, "-i", std::make_pair(false, "")))}
        , m_formatInputFiles {paramValueOf(argc, argv, "-f", std::make_pair(false, "offsets"))}
    {
    }

    /**
     * @brief Gets the configuration file path.
     * @return Configuration file path.
     */
    const std::string& getConfigurationFilePath() const
    {
        return m_configurationFilePath;
    }

    /**
     * @brief Gets the wait time.
     * @return Wait time.
     */
    size_t getWaitTime() const
    {
        return std::stoull(m_waitTime);
    }

    /**
     * @brief Gets the input files.
     * @return Input files.
     */
    const std::vector<std::string>& getInputFiles() const
    {
        return m_inputFiles;
    }

    /**
     * @brief Gets the format of the input files.
     * @return Format of the input files.
     */
    const std::string& getFormatInputFiles() const
    {
        return m_formatInputFiles;
    }

    /**
     * @brief Shows the help to the user.
     */
    static void showHelp()
    {
        std::cout << "\nUsage: DatabaseFeedManager <option(s)>\n"
                  << "Options:\n"
                  << "\t-h \t\t\tShow this help message\n"
                  << "\t-c CONFIG_FILE\t\tSpecifies the configuration file.\n"
                  << "\t-s WAIT_TIME\t\tSpecifies the wait before exit.\n"
                  << "\t-i INPUT_FILES\t\tSpecifies the input files.\n"
                  << "\t-f [offsets | raw]\tSpecifies the format of the input files.\n"
                  << "\nExample:"
                  << "\n\t./DatabaseFeedManager -c config.json\n"
                  << "\n\t./DatabaseFeedManager -c config.json -s 10\n"
                  << "\n\t./DatabaseFeedManager -c config.json -f offsets -i file1.json,file2.json\n"
                  << std::endl;
    }

private:
    static std::string paramValueOf(const int argc,
                                    const char* argv[],
                                    const std::string& switchValue,
                                    const std::pair<bool, std::string>& required = std::make_pair(true, ""))
    {
        for (int i = 1; i < argc; ++i)
        {
            const std::string currentValue {argv[i]};

            if (currentValue == switchValue && i + 1 < argc)
            {
                // Switch found
                return argv[i + 1];
            }
        }

        if (required.first)
        {
            throw std::runtime_error {"Switch value: " + switchValue + " not found."};
        }

        return required.second;
    }

    static std::vector<std::string> splitActions(const std::string& values)
    {
        std::vector<std::string> actionsValues;
        std::stringstream ss {values};

        while (ss.good())
        {
            std::string substr;
            getline(ss, substr, ','); // Getting each string between ',' character
            actionsValues.push_back(std::move(substr));
        }

        return actionsValues;
    }

    const std::string m_configurationFilePath;
    const std::string m_waitTime;
    const std::vector<std::string> m_inputFiles;
    const std::string m_formatInputFiles;
};

#endif // _CMD_ARGS_PARSER_HPP_
